home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 501-525 / disk_519 / oaklisp / src.lzh / gc.c < prev    next >
C/C++ Source or Header  |  1991-06-15  |  15KB  |  728 lines

  1. /* Copyright (C) 1987,8,9 Barak Pearlmutter and Kevin Lang. */
  2.  
  3. /* This file contains the garbage collector. */
  4.  
  5. #include <stdio.h>
  6. #include "emulator.h"
  7. #include "stacks.h"
  8. #include "gc.h"
  9.  
  10. #ifndef CMUCS
  11. #ifdef unix
  12. #include <sys/vadvise.h>
  13. #endif
  14. #endif
  15.  
  16. extern stack val_stk, cxt_stk;
  17.  
  18. bool gc_shutup=FALSE, full_gc;
  19.  
  20.  
  21.  
  22. #define GC_TOUCH(x)            \
  23. {                    \
  24.   if ((x)&PTR_MASK)            \
  25.     {                    \
  26.       ref *MACROp = ANY_TO_PTR((x));    \
  27.                     \
  28.       if (OLD_PTR(MACROp))        \
  29.     (x) = gc_touch0((x));        \
  30.     }                    \
  31. }
  32.  
  33. #define GC_TOUCH_PTR(r,o)                    \
  34. {                                \
  35.   (r) = REF_TO_PTR(gc_touch0(PTR_TO_REF((r)-(o)))) + (o);    \
  36. }
  37.  
  38.  
  39.  
  40. #define LOC_TOUCH(x)                \
  41. {                        \
  42.   if (TAG_IS((x),LOC_TAG))            \
  43.     {                        \
  44.       ref *MACROp = LOC_TO_PTR((x));        \
  45.                         \
  46.       if (OLD_PTR(MACROp))            \
  47.     (x)=loc_touch0((x),0);            \
  48.     }                        \
  49. }
  50.  
  51. #define LOC_TOUCH_PTR(x)                \
  52. {                            \
  53.   (x) = LOC_TO_PTR(loc_touch0(PTR_TO_LOC(x),1));    \
  54. }
  55.  
  56.  
  57.  
  58. space new, spatic, old;
  59. ref *free_point;
  60.  
  61. unsigned long transport_count;
  62. unsigned long loc_transport_count;
  63.  
  64. ref pre_gc_nil;
  65.  
  66.  
  67. #define GC_EXAMINE_BUFFER_SIZE 20
  68.  
  69. ref gc_examine_buffer[GC_EXAMINE_BUFFER_SIZE];
  70. ref *gc_examine_ptr = &gc_examine_buffer[0];
  71.  
  72.  
  73.  
  74.  
  75.  
  76. void gc_printref(refin)
  77.      ref refin;
  78. {
  79.   long i;
  80.   char suffix = '?';
  81.  
  82.   if (refin&PTR_MASK)
  83.     {
  84.       ref *p = ANY_TO_PTR(refin);
  85.       
  86.       if (SPATIC_PTR(p))
  87.     {
  88.       i = p - spatic.start;
  89.       suffix = 's';
  90.     }
  91.       else if (NEW_PTR(p))
  92.     {
  93.       i = p - new.start + spatic.size;
  94.       suffix = 'n';
  95.     }
  96.       else if (OLD_PTR(p))
  97.     {
  98.       i = p - old.start + spatic.size;
  99.       suffix = 'o';
  100.     }
  101.       else
  102.     i = (long)p >> 2;
  103.  
  104.       fprintf(stderr, "%ld~%ld%c", i, refin&TAG_MASK, suffix);
  105.     }
  106.   else
  107.     fprintf(stderr, "%ld~%ld", refin>>2, refin&TAG_MASK);
  108. }
  109.  
  110.  
  111.  
  112.  
  113. #define GC_NULL(r) ((r)==pre_gc_nil || (r)==e_nil)
  114.  
  115.  
  116.  
  117.  
  118.  
  119. /* This variant of get_length has to follow forwarding pointers so
  120.    that it will work in the middle of a gc, when an object's type might
  121.    already have been transported. */
  122.  
  123. unsigned long gc_get_length(x)
  124.      ref x;
  125. {
  126.   if TAG_IS(x,PTR_TAG)
  127.     {
  128.       ref typ = REF_SLOT(x,0);
  129.       ref vlen_p = REF_SLOT(typ, TYPE_VAR_LEN_P_OFF);
  130.       ref len;
  131.       
  132.       /* Is vlen_p forwarded? */
  133.       if (TAG_IS(vlen_p,LOC_TAG)) 
  134.     vlen_p = *LOC_TO_PTR(vlen_p);
  135.  
  136.       /* Is this object variable length? */
  137.       if (GC_NULL(vlen_p))
  138.     {
  139.       /* Not variable length. */
  140.       len = REF_SLOT(typ, TYPE_LEN_OFF);
  141.  
  142.       /* Is length forwarded? */
  143.       if (TAG_IS(len,LOC_TAG)) 
  144.         len = *LOC_TO_PTR(len);
  145.       
  146.       return REF_TO_INT(len);
  147.     }
  148.       else
  149.     return REF_TO_INT(REF_SLOT(x,1));
  150.     }
  151.   else
  152.     {
  153.       fprintf(stderr, "; WARNING!!!  gc_get_length(");
  154.       gc_printref(x);
  155.       fprintf(stderr, ") called; only a tag of %d is allowed.\n", PTR_TAG);
  156.       return 0;
  157.     }
  158. }
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167. ref gc_touch0(r)
  168.      ref r;
  169. {
  170.   ref *p = ANY_TO_PTR(r);
  171.  
  172.   if (OLD_PTR(p))
  173.  
  174.     if (r&1)
  175.       {
  176.     ref type_slot = *p;
  177.     if (TAG_IS(type_slot,LOC_TAG))
  178.       /* Already been transported. */
  179.       /* Tag magic transforms this:
  180.          return(PTR_TO_REF(LOC_TO_PTR(type_slot)));
  181.          to this: */
  182.       return type_slot|1L;
  183.     else
  184.       {
  185.         /* Transport it */
  186.         long i;
  187.         long len = gc_get_length(r);
  188.         ref *new_place = free_point;
  189.         ref *p0 = p;
  190.         ref *q0 = new_place;
  191.  
  192.         transport_count += 1;
  193.  
  194.         /*
  195.           fprintf(stderr, "About to transport ");
  196.           gc_printref(r);
  197.           fprintf(stderr, " len = %ld.\n", len);
  198.           */
  199.  
  200.         free_point += len;
  201. #ifndef FAST
  202.         if (free_point >= new.end)
  203.           {
  204.         fprintf(stderr, "\n; New space exhausted while transporting ");
  205.         gc_printref(r);
  206.         fprintf(stderr, ".\n; This indicates a bug in the garbage collector.\n");
  207.         exit(1);
  208.           }
  209. #endif
  210.  
  211.         for (i=0; i<len; i++, p0++, q0++)
  212.           {
  213.         *q0 = *p0;
  214.         *p0 = PTR_TO_LOC(q0);
  215.           }
  216.  
  217.         return(PTR_TO_REF(new_place));
  218.       }
  219.       }
  220.     else
  221.       {
  222.     /* Follow the chain of locatives to oldspace until we find a
  223.        real object or a circularity. */
  224.     ref r0 = r, r1 = *p, *pp;
  225.     /* int chain_len = 1; */
  226.  
  227.     while (TAG_IS(r1,LOC_TAG) && (pp = LOC_TO_PTR(r1), OLD_PTR(pp)))
  228.       {
  229.         if (r0==r1)
  230.           {
  231.         /* fprintf(stderr, "Circular locative chain.\n"); */
  232.         goto forwarded_loc;
  233.           }
  234.         r0 = *LOC_TO_PTR(r0);
  235.         r1 = *pp;
  236.         /* chain_len += 1; */
  237.         
  238.         if (r0==r1)
  239.           {
  240.         /* fprintf(stderr, "Circular locative chain.\n"); */
  241.         goto forwarded_loc;
  242.           }
  243.         if (!TAG_IS(r1,LOC_TAG) || (pp = LOC_TO_PTR(r1), !OLD_PTR(pp)))
  244.           break;
  245.  
  246.         r1 = *pp;
  247.         /* chain_len += 1; */
  248.       }
  249.  
  250.     /* We're on an object, so touch it. */
  251.     /* 
  252.       fprintf(stderr, "Locative chain followed to ");
  253.       gc_printref(r1);
  254.       fprintf(stderr, " requiring %d dereferences.\n", chain_len);
  255.       */
  256.     GC_TOUCH(r1);
  257.     /* (void)gc_touch(r1); */
  258.  
  259.     /* Now see if we're looking at a forwarding pointer. */
  260.       forwarded_loc:
  261.     return(r);
  262.       }
  263.   else
  264.     return(r);
  265. }
  266.  
  267.  
  268.  
  269.  
  270.  
  271. ref loc_touch0(r, warn_if_unmoved)
  272.      ref r;
  273.      bool warn_if_unmoved;
  274. {
  275.   ref *p = LOC_TO_PTR(r);
  276.  
  277.   if (OLD_PTR(p))
  278.     {
  279.       /* A locative into old space.  See if it's been transported yet. */
  280.       ref r1 = *p;
  281.       if (TAG_IS(r1,LOC_TAG) && NEW_PTR(LOC_TO_PTR(r1)))
  282.     /* Already been transported. */
  283.     return(r1);
  284.       else
  285.     {
  286.       /* Better transport this lonely cell. */
  287.  
  288.       ref *new_place = free_point++; /* make a new cell. */
  289.       ref new_r = PTR_TO_LOC(new_place);
  290.           
  291. #ifndef FAST
  292.       if (free_point >= new.end)
  293.         {
  294.           fprintf(stderr, "\n; New space exhausted while transporting the cell ");
  295.           gc_printref(r);
  296.           fprintf(stderr, ".\n; This indicates a bug in the garbage collector.\n");
  297.           exit(1);
  298.         }
  299. #endif
  300.  
  301.       *p = new_r;        /* Record the transportation. */
  302.  
  303.       /* Put the right value in the new cell. */
  304.  
  305.       *new_place =
  306.         TAG_IS(r1,PTR_TAG) && (p = REF_TO_PTR(r1),OLD_PTR(p))
  307.           ? *p|1 : r1;
  308.       /* ? PTR_TO_REF(REF_TO_PTR(*p)) : r1; */
  309.  
  310.       loc_transport_count += 1;
  311.  
  312.       if (warn_if_unmoved)
  313.         {
  314.           fprintf(stderr, "\nWarning: the locative ");
  315.           gc_printref(r);
  316.           fprintf(stderr, " has just had its raw cell moved.\n");
  317.         }
  318.  
  319.       return(new_r);
  320.     }
  321.     }
  322.   else
  323.     return(r);            /* Not a locative into old space. */
  324. }
  325.  
  326.  
  327.  
  328.  
  329. void scavenge()
  330. {
  331.   ref *scavenge_p;
  332.  
  333.   for (scavenge_p = new.start; scavenge_p < free_point; scavenge_p += 1)
  334.     GC_TOUCH(*scavenge_p);
  335. }
  336.  
  337.  
  338.  
  339.  
  340. void loc_scavenge()
  341. {
  342.   ref *scavenge_p;
  343.  
  344.   for (scavenge_p = new.start; scavenge_p < free_point; scavenge_p += 1)
  345.     LOC_TOUCH(*scavenge_p);
  346. }
  347.  
  348.  
  349.  
  350.  
  351.  
  352.  
  353. #ifndef FAST
  354.  
  355. #define GGC_CHECK(r) GC_CHECK(r,"r")
  356.  
  357. /* True if r seems like a messed up reference. */
  358. bool gc_check(r)
  359.      ref r;
  360. {
  361.   return (r&PTR_MASK) && !NEW_PTR(ANY_TO_PTR(r))
  362.     && (full_gc || !SPATIC_PTR(ANY_TO_PTR(r)));
  363. }
  364.  
  365.  
  366.  
  367. void GC_CHECK(x,st)
  368.   ref x;
  369.   char st[];
  370. {
  371.   if (gc_check((x)))
  372.     {
  373.       fprintf(stderr, "%s = ", (st));
  374.       gc_printref((x));
  375.       if (OLD_PTR(ANY_TO_PTR(x)))
  376.     {
  377.       fprintf(stderr, ",  cell contains ");
  378.       gc_printref(*ANY_TO_PTR(x));
  379.     }
  380.       fprintf(stderr, "\n");
  381.     }
  382. }
  383.  
  384.  
  385.  
  386.  
  387. void GC_CHECK1(x,st,i)
  388.      ref x;
  389.      char st[];
  390.      long i;
  391. {
  392.   if (gc_check((x)))
  393.     {
  394.       fprintf(stderr, (st), (i));
  395.       gc_printref((x));
  396.       if (OLD_PTR(ANY_TO_PTR(x)))
  397.     {
  398.       fprintf(stderr, ",  cell contains ");
  399.       gc_printref(*ANY_TO_PTR(x));
  400.     }
  401.       fprintf(stderr, "\n");
  402.     }
  403. }
  404.  
  405. #endif
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412. unsigned short *pc_touch(o_pc)
  413.      unsigned short *o_pc;
  414. {
  415.   ref *pcell = (ref *)((unsigned long)o_pc & ~TAG_MASKL);
  416.  
  417.   LOC_TOUCH_PTR(pcell);
  418.   return
  419.     (unsigned short *)((unsigned long)pcell | (unsigned long)o_pc&TAG_MASK);
  420. }
  421.  
  422.  
  423.  
  424. void set_external_full_gc(full)
  425.      bool full;
  426. {
  427.   full_gc = full;
  428. }
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435. void gc(pre_dump, full_gc, reason, amount)
  436.      bool pre_dump;        /* About to dump world?  (discards stacks) */
  437.      bool full_gc;        /* Reclaim garbage from spatic space too? */
  438.      char *reason;        /* The reason for this GC, in English. */
  439.      long amount;        /* The amount of space that is needed. */
  440. {
  441.   long old_taken;
  442.   ref *p;
  443.  
  444. #ifdef mac
  445.   GrafPtr savePort;
  446.   GetPort(&savePort);
  447. #endif
  448.  
  449.   /* The full_gc flag is also a global to avoid ugly parameter passing. */
  450.   set_external_full_gc(full_gc);
  451.  
  452.   if (!gc_shutup)
  453.     fprintf(stderr, "\n; %sGC due to %s.\n", full_gc ? "Full " : "", reason);
  454.  
  455.  gc_top:
  456.  
  457.   if (trace_gc && !pre_dump)
  458.     {
  459.       fprintf(stderr, "value ");
  460.       dump_stack_proc(&val_stk);
  461.       fprintf(stderr, "context ");
  462.       dump_stack_proc(&cxt_stk);
  463.     }
  464.  
  465.   if (!gc_shutup) fprintf(stderr, "; Flipping...");
  466.  
  467.   old_taken = free_point - new.start;
  468.   old = new;
  469.  
  470.   if (full_gc)
  471.     new.size += spatic.size;
  472.   else
  473.     new.size = e_next_newspace_size;
  474.  
  475.   alloc_space(&new);
  476.   free_point = new.start;
  477.  
  478.   transport_count = 0;
  479.  
  480.   if (!gc_shutup) fprintf(stderr, " rooting...");
  481.  
  482.   {
  483.     /* Hit the registers: */
  484.  
  485.     pre_gc_nil = e_nil;
  486.     GC_TOUCH(e_nil);
  487.     GC_TOUCH(e_boot_code);
  488.  
  489.     if (!pre_dump)
  490.       {
  491.     GC_TOUCH(e_t);
  492.     GC_TOUCH(e_fixnum_type);
  493.     GC_TOUCH(e_loc_type);
  494.     GC_TOUCH(e_cons_type);
  495.     GC_TOUCH_PTR(e_subtype_table,2);
  496.     /* e_bp is a locative, but a pointer to the object should exist, so we
  497.        need only touch it in the locative pass. */
  498.     GC_TOUCH_PTR(e_env,0);
  499.     /* e_nargs is a fixnum.  Nor is it global... */
  500.     GC_TOUCH(e_env_type);
  501.     GC_TOUCH_PTR(e_argless_tag_trap_table,2);
  502.     GC_TOUCH_PTR(e_arged_tag_trap_table,2);
  503.     GC_TOUCH(e_object_type);
  504.     GC_TOUCH(e_segment_type);
  505.     GC_TOUCH(e_code_segment);
  506.     GC_TOUCH(e_current_method);
  507.     GC_TOUCH(e_uninitialized);
  508.     GC_TOUCH(e_method_type);
  509.  
  510.     for (p = &gc_examine_buffer[0]; p < gc_examine_ptr; p++)
  511.       GC_TOUCH(*p);
  512.  
  513.     gc_prepare(&val_stk);
  514.     gc_prepare(&cxt_stk);
  515.  
  516.     /* Scan the stacks. */
  517.     for (p = &val_stk.data[0]; p <= val_stk.ptr; p++)
  518.       GC_TOUCH(*p);
  519.       
  520.     for (p = &cxt_stk.data[0]; p <= cxt_stk.ptr; p++)
  521.       GC_TOUCH(*p);
  522.  
  523.     /* Scan the stack segments. */
  524.     GC_TOUCH(val_stk.segment);
  525.     GC_TOUCH(cxt_stk.segment);
  526.  
  527.     /* Scan static space. */
  528.     if (!full_gc)
  529.       for (p = spatic.start; p<spatic.end; p++)
  530.         GC_TOUCH(*p);
  531.       }
  532.  
  533.   
  534.     /* Scavenge. */
  535.     if (!gc_shutup)
  536.       fprintf(stderr, " scavenging...");
  537.     scavenge();
  538.  
  539.     if (!gc_shutup)
  540.       fprintf(stderr, " %ld object%s transported.\n",
  541.           transport_count, transport_count != 1 ? "s" : "");
  542.  
  543.  
  544.  
  545.     /* Clean up the locatives. */
  546.     if (!gc_shutup)
  547.       fprintf(stderr, "; Scanning locatives...");
  548.     loc_transport_count = 0;
  549.   
  550.     if (!pre_dump)
  551.       {
  552.     LOC_TOUCH_PTR(e_bp);
  553.     e_pc = pc_touch(e_pc);
  554.  
  555.     LOC_TOUCH(e_uninitialized);
  556.  
  557.     for (p = &gc_examine_buffer[0]; p < gc_examine_ptr; p++)
  558.       LOC_TOUCH(*p);
  559.  
  560.     for (p = &val_stk.data[0]; p <= val_stk.ptr; p++)
  561.       LOC_TOUCH(*p);
  562.       
  563.     for (p = &cxt_stk.data[0]; p <= cxt_stk.ptr; p++)
  564.       LOC_TOUCH(*p);
  565.  
  566.     /* Scan spatic space. */
  567.     if (!full_gc)
  568.       for (p = spatic.start; p<spatic.end; p++)
  569.         LOC_TOUCH(*p);
  570.       }
  571.   
  572.     if (!gc_shutup)
  573.       fprintf(stderr, " scavenging...");
  574.     loc_scavenge();
  575.  
  576.     if (!gc_shutup)
  577.       fprintf(stderr, " %ld naked cell%s transported.\n",
  578.           loc_transport_count, loc_transport_count != 1 ? "s" : "");
  579.  
  580.  
  581.     /* Discard weak pointers whose targets have not been transported. */
  582.     if (!gc_shutup)
  583.       fprintf(stderr, "; Scanning weak pointer table...");
  584.     {
  585.       long count = post_gc_wp();
  586.  
  587.       if (!gc_shutup)
  588.     fprintf(stderr, " %ld entr%s discarded.\n",
  589.         count, count != 1 ? "ies" : "y");
  590.     }
  591.   }
  592.   
  593.  
  594. #ifndef FAST
  595.   {
  596.     /* Check GC consistency. */
  597.  
  598.     if (!gc_shutup)
  599.       fprintf(stderr, "; Checking consistency...\n");
  600.  
  601.     GGC_CHECK(e_nil);
  602.     GGC_CHECK(e_boot_code);
  603.  
  604.     if (!pre_dump)
  605.       {
  606.     GGC_CHECK(e_t);
  607.     GGC_CHECK(e_fixnum_type);
  608.     GGC_CHECK(e_loc_type);
  609.     GGC_CHECK(e_cons_type);
  610.     GC_CHECK(PTR_TO_REF(e_subtype_table-2),"e_subtype_table");
  611.     GC_CHECK(PTR_TO_LOC(e_bp),"PTR_TO_LOC(e_bp)");
  612.     GC_CHECK(PTR_TO_REF(e_env),"e_env");
  613.     /* e_nargs is a fixnum.  Nor is it global... */
  614.     GGC_CHECK(e_env_type);
  615.     GC_CHECK(PTR_TO_REF(e_argless_tag_trap_table-2),"e_argless_tag_trap_table");
  616.     GC_CHECK(PTR_TO_REF(e_arged_tag_trap_table-2),"e_arged_tag_trap_table");
  617.     GGC_CHECK(e_object_type);
  618.     GGC_CHECK(e_segment_type);
  619.     GGC_CHECK(e_code_segment);
  620.     GGC_CHECK(e_current_method);
  621.     GGC_CHECK(e_uninitialized);
  622.     GGC_CHECK(e_method_type);
  623.  
  624.     /* Scan the stacks. */
  625.     for (p = &val_stk.data[0]; p <= val_stk.ptr; p++)
  626.       GC_CHECK1(*p, "val_stk.data[%d] = ", (long)(p - &val_stk.data[0]));
  627.  
  628.     for (p = &cxt_stk.data[0]; p <= cxt_stk.ptr; p++)
  629.       GC_CHECK1(*p, "cxt_stk.data[%d] = ", (long)(p - &cxt_stk.data[0]));
  630.  
  631.     GGC_CHECK(val_stk.segment);
  632.     GGC_CHECK(cxt_stk.segment);
  633.  
  634.     /* Make sure the program counter is okay. */
  635.     GC_CHECK((ref)((ref)e_pc|LOC_TAG), "e_pc");
  636.       }
  637.  
  638.     /* Scan the heap. */
  639.  
  640.     if (!full_gc)
  641.       for (p = spatic.start; p<spatic.end; p++)
  642.     GC_CHECK1(*p, "static_space[%ld] = ", (long)(p-spatic.start));
  643.  
  644.     for (p = new.start; p<free_point; p++)
  645.       GC_CHECK1(*p, "new_space[%ld] = ", (long)(p-new.start));
  646.   }
  647. #endif                /* ndef FAST */
  648.  
  649.   /* Hopefully there are no more references into old space. */
  650.   free_space(&old);
  651.   if (full_gc) free_space(&spatic);
  652.  
  653. #ifndef CMUCS
  654. #ifdef unix
  655. #ifdef VA_FLUSH
  656.   /* Tell the virtual memory system that it's recent statistics are useless. */
  657.   vadvise(VA_FLUSH);
  658. #endif
  659. #endif
  660. #endif
  661.  
  662.   if (trace_gc && !pre_dump)
  663.     {
  664.       fprintf(stderr, "val_stk ");
  665.       dump_stack_proc(&val_stk);
  666.       fprintf(stderr, "cxt_stk ");
  667.       dump_stack_proc(&cxt_stk);
  668.     }
  669.  
  670.  
  671.   {
  672.     long new_taken = free_point - new.start;
  673.     long old_total = old_taken + (full_gc ? spatic.size : 0);
  674.     long reclaimed = old_total - new_taken;
  675.  
  676.     if (!gc_shutup)
  677.       {
  678.     fprintf(stderr, "; GC complete.  %ld ", old_total);
  679.     if (full_gc) fprintf(stderr, "(%ld+%ld) ", spatic.size, old_taken);
  680.     fprintf(stderr, "compacted to %ld; %ld (%ld%%) garbage.\n",
  681.         new_taken, reclaimed, (100*reclaimed)/old_total);
  682.       }
  683.  
  684.     /* Make the next new space bigger if the current was too small. */
  685.     if (!full_gc && !pre_dump && (RECLAIM_FACTOR*new_taken + amount > new.size))
  686.       {
  687.     e_next_newspace_size = RECLAIM_FACTOR*new_taken + amount;
  688.     if (!gc_shutup)
  689.       fprintf(stderr, "; Expanding next new space from %ld to %ld (%d%%).\n",
  690.           new.size, e_next_newspace_size,
  691.           (100*(e_next_newspace_size - new.size))/new.size);
  692.     if ((new.end - free_point) < amount)
  693.       {
  694.         reason = "immediate new space expansion necessity";
  695.         goto gc_top;
  696.       }
  697.       }
  698.  
  699.     if (full_gc && !pre_dump)
  700.       {
  701.     /* Ditch old spatic, move new to spatic, and reallocate new. */
  702.     free_space(&spatic);
  703.     spatic = new;
  704.     realloc_space(&spatic, free_point);
  705.  
  706.     if (!gc_shutup && e_next_newspace_size != original_newspace_size)
  707.       fprintf(stderr, "; Setting new space size to %ld.\n", original_newspace_size);
  708.     new.size = e_next_newspace_size = original_newspace_size;
  709.     if (e_next_newspace_size <= amount)
  710.       {
  711.         e_next_newspace_size = RECLAIM_FACTOR*amount;
  712.         if (!gc_shutup)
  713.           fprintf(stderr, "; Expanding next new space from %ld to %ld (%d%%).\n",
  714.               new.size, e_next_newspace_size,
  715.               (100*(e_next_newspace_size - new.size))/new.size);
  716.         new.size = e_next_newspace_size;
  717.       }
  718.     alloc_space(&new);
  719.     free_point = new.start;
  720.       }
  721.     if (!gc_shutup)
  722.       fflush_stdout();
  723.   }
  724. #ifdef mac
  725.   SetPort(savePort);
  726. #endif
  727. }
  728.